﻿using System.Linq;
using System.Text;

namespace ThingsGateway.Foundation
{
    /// <summary>
    /// 所有数据转换类的静态辅助方法<br />
    /// </summary>
    public static class ByteConverterHelper
    {

        #region Public Methods

        /// <summary>
        ///设备地址可以带有的额外信息包含：
        /// DATA=XX;
        /// TEXT=XX;
        /// BCD=XX;
        /// LEN=XX;
        ///<br></br>
        /// 解析地址的附加<see cref="DataFormat"/> />参数方法，比如你的地址是dataformat=DataFormat.ABCD;1
        /// 可以提取出"dataformat"的值的同时，并去掉address中的全部额外信息，包含字符串信息等，
        /// 如果"dataformat"不存在的话，不修改<see cref="IThingsGatewayBitConverter"/>对象<br />
        /// </summary>
        /// <param name="address">复杂的地址格式</param>
        /// <param name="defaultTransform">默认的数据转换信息</param>
        public static IThingsGatewayBitConverter ExtractTransformParameter(
          ref string address,
          IThingsGatewayBitConverter defaultTransform)
        {
            var strs = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            var format = strs.FirstOrDefault(m => !m.Trim().ToUpper().Contains("DATA="))?.ToUpper();
            DataFormat dataFormat = DataFormat.None;
            switch (format)
            {
                case "DATA=ABCD":
                    dataFormat = DataFormat.ABCD;
                    break;
                case "DATA=BADC":
                    dataFormat = DataFormat.BADC;
                    break;
                case "DATA=DCBA":
                    dataFormat = DataFormat.DCBA;
                    break;
                case "DATA=CDAB":
                    dataFormat = DataFormat.CDAB;
                    break;
            }

            //去除以上的额外信息
            address = String.Join(";", strs.Where(m =>
            (!m.Trim().ToUpper().Contains("DATA=")) &&
            (!m.Trim().ToUpper().Contains("TEXT=")) &&
            (!m.Trim().ToUpper().Contains("BCD=")) &&
            (!m.Trim().ToUpper().Contains("LEN="))
            ));

            return dataFormat != defaultTransform.DataFormat && dataFormat != DataFormat.None ?
                    defaultTransform.CreateByDateFormat(dataFormat) :
                    defaultTransform;
        }

        /// <summary>
        /// <inheritdoc cref="ExtractTransformParameter(ref string, IThingsGatewayBitConverter)"/>
        /// </summary>
        public static void ExtractTransformParameter(ref string address)
        {
            var strs = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            //去除以上的额外信息
            address = String.Join(";", strs.Where(m =>
            (!m.Trim().ToUpper().Contains("DATA=")) &&
            (!m.Trim().ToUpper().Contains("TEXT=")) &&
            (!m.Trim().ToUpper().Contains("BCD=")) &&
            (!m.Trim().ToUpper().Contains("LEN="))
            ));
        }


        /// <summary>
        /// <inheritdoc cref="ExtractTransformParameter(ref string, IThingsGatewayBitConverter)"/>
        /// </summary>
        public static IThingsGatewayBitConverter ExtractTransformParameter(
          ref string address,
          IThingsGatewayBitConverter defaultTransform,
          out Encoding encoding,
          out ushort length,
          out BCDFormat bCDFormat)
        {
            encoding = Encoding.Default;
            length = 0;
            bCDFormat = BCDFormat.C8421;
            if (address.IsNullOrEmptyEx()) return defaultTransform;
            var strs = address.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            var format = strs.FirstOrDefault(m => m.Trim().ToUpper().Contains("DATA="))?.ToUpper();
            DataFormat dataFormat = DataFormat.None;
            switch (format)
            {
                case "DATA=ABCD":
                    dataFormat = DataFormat.ABCD;
                    break;
                case "DATA=BADC":
                    dataFormat = DataFormat.BADC;
                    break;
                case "DATA=DCBA":
                    dataFormat = DataFormat.DCBA;
                    break;
                case "DATA=CDAB":
                    dataFormat = DataFormat.CDAB;
                    break;
            }

            var strencoding = strs.FirstOrDefault(m => m.Trim().ToUpper().Contains("TEXT="))?.ToUpper();
            encoding = Encoding.Default;
            switch (strencoding)
            {
                case "TEXT=UTF8":
                    encoding = Encoding.UTF8;
                    break;
                case "TEXT=ASCII":
                    encoding = Encoding.ASCII;
                    break;
                case "TEXT=Default":
                    encoding = Encoding.Default;
                    break;
                case "TEXT=Unicode":
                    encoding = Encoding.Unicode;
                    break;
            }

            var strlen = strs.FirstOrDefault(m => m.Trim().ToUpper().Contains("STRLEN="))?.ToUpper().Replace("STRLEN=", "");
            length = strlen.IsNullOrEmptyEx() ? (ushort)0 : Convert.ToUInt16(strlen);

            var strbCDFormat = strs.FirstOrDefault(m => m.Trim().ToUpper().Contains("BCD="))?.ToUpper();
            bCDFormat = BCDFormat.C8421;
            switch (strbCDFormat)
            {
                case "BCD=C8421":
                    bCDFormat = BCDFormat.C8421;
                    break;
                case "BCD=C2421":
                    bCDFormat = BCDFormat.C2421;
                    break;
                case "BCD=C3":
                    bCDFormat = BCDFormat.C3;
                    break;
                case "BCD=C5421":
                    bCDFormat = BCDFormat.C5421;
                    break;
                case "BCD=Gray":
                    bCDFormat = BCDFormat.Gray;
                    break;
            }

            //去除以上的额外信息
            address = String.Join(";", strs.Where(m =>
            (!m.Trim().ToUpper().Contains("DATA=")) &&
            (!m.Trim().ToUpper().Contains("TEXT=")) &&
            (!m.Trim().ToUpper().Contains("BCD=")) &&
            (!m.Trim().ToUpper().Contains("LEN="))
            ));

            return dataFormat != defaultTransform.DataFormat && dataFormat != DataFormat.None ?
                    defaultTransform.CreateByDateFormat(dataFormat) :
                    defaultTransform;

        }


        /// <summary>结果转换操作的基础方法，需要支持类型，及转换的委托</summary>
        /// <typeparam name="TResult">结果类型</typeparam>
        /// <param name="result">源结果</param>
        /// <returns>转换结果</returns>
        public static OperResult<TResult> GetResultFromArray<TResult>(
          OperResult<TResult[]> result)
        {
            return GetSuccessResultFromOther(result, m => m[0]);
        }

        /// <summary>结果转换操作的基础方法，需要支持类型，及转换的委托，并捕获转换时的异常方法</summary>
        /// <typeparam name="TResult">结果类型</typeparam>
        /// <param name="result">源</param>
        /// <param name="translator">实际转换的委托</param>
        /// <returns>转换结果</returns>
        public static OperResult<TResult> GetResultFromBytes<TResult>(
          OperResult<byte[]> result,
          Func<byte[], TResult> translator)
        {
            try
            {
                return result.IsSuccess ? OperResult.CreateSuccessResult(translator(result.Content)) : result.Copy<TResult>();
            }
            catch (Exception ex)
            {
                OperResult<TResult> resultFromBytes = new OperResult<TResult>
                {
                    Message = string.Format("{0} {1} : Length({2}) {3}", Resource.DataTransformError, result.Content.ToHexString(), result.Content.Length, ex.Message)
                };
                return resultFromBytes;
            }
        }

        /// <summary>使用指定的转换方法，来获取到实际的结果对象内容</summary>
        public static OperResult GetResultFromOther<TIn>(
          OperResult<TIn> result,
          Func<TIn, OperResult> trans)
        {
            return !result.IsSuccess ? result : trans(result.Content);
        }

        /// <summary>使用指定的转换方法，来获取到实际的结果对象内容</summary>
        public static OperResult<TResult> GetResultFromOther<TResult, TIn>(
          OperResult<TIn> result,
          Func<TIn, OperResult<TResult>> trans)
        {
            return !result.IsSuccess ? result.Copy<TResult>() : trans(result.Content);
        }



        /// <summary>使用指定的转换方法，来获取到实际的结果对象内容，所转换的规则</summary>
        public static OperResult<TResult> GetSuccessResultFromOther<TResult, TIn>(
          OperResult<TIn> result,
          Func<TIn, TResult> trans)
        {
            return !result.IsSuccess ? result.Copy<TResult>() : OperResult.CreateSuccessResult(trans(result.Content));
        }

        #endregion Public Methods

    }
}